package com.cmc.cloud.cmclink.doc.service.impl;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.annotation.Resource;

import com.cmc.cloud.cmclink.doc.util.sepcial.CommonUtil;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import com.cmc.cloud.cmclink.doc.constants.errorconstant.TerminalDgTeuLimitedErrorCodeConstants;
import com.cmc.cloud.cmclink.doc.convert.TerminalDgTeuLimitedConvert;
import com.cmc.cloud.cmclink.doc.entity.TerminalDgTeuLimitedDO;
import com.cmc.cloud.cmclink.doc.mapper.TerminalDgTeuLimitedMapper;
import com.cmc.cloud.cmclink.doc.service.TerminalDgTeuLimitedService;
import com.cmc.cloud.cmclink.doc.vo.special.terminaldgteulimitedvo.TerminalDgTeuLimitedBaseVO;
import com.cmc.cloud.cmclink.doc.vo.special.terminaldgteulimitedvo.TerminalDgTeuLimitedCreateReqVO;
import com.cmc.cloud.cmclink.doc.vo.special.terminaldgteulimitedvo.TerminalDgTeuLimitedPageReqVO;
import com.cmc.cloud.cmclink.doc.vo.special.terminaldgteulimitedvo.TerminalDgTeuLimitedUpdateReqVO;
import com.cmes.framework.common.exception.util.ServiceExceptionUtil;
import com.cmes.framework.common.pojo.PageResult;
import com.cmes.framework.mybatis.core.query.LambdaQueryWrapperX;

/**
 * 港口各码头危险品单船作业限量维护 Service 实现类
 *
 * @author 集运管理员
 */
@Service
@Validated
public class TerminalDgTeuLimitedServiceImpl implements TerminalDgTeuLimitedService {

    @Resource
    private TerminalDgTeuLimitedMapper terminalDgTeuLimitedMapper;

    @Override
    public void createTerminalDgTeuLimited(TerminalDgTeuLimitedCreateReqVO createReqVO) {
        if (createReqVO.getStartDate().isAfter(createReqVO.getEndDate())) {
            throw ServiceExceptionUtil.exception(TerminalDgTeuLimitedErrorCodeConstants.TERMINAL_DG_TEU_START_GT_END);
        }

        // 校验有效期是否存在重叠
        if (dateOverlap(createReqVO)) {
            throw ServiceExceptionUtil.exception(TerminalDgTeuLimitedErrorCodeConstants.TERMINAL_DG_TEU_DATE_OVERLAP);
        }

        // 插入
        TerminalDgTeuLimitedDO terminalDgTeuLimited = TerminalDgTeuLimitedConvert.INSTANCE.convert(createReqVO);
        terminalDgTeuLimitedMapper.insert(terminalDgTeuLimited);
    }

    @Override
    public void updateTerminalDgTeuLimited(TerminalDgTeuLimitedUpdateReqVO updateReqVO) {
        if (updateReqVO.getStartDate().isAfter(updateReqVO.getEndDate())) {
            throw ServiceExceptionUtil.exception(TerminalDgTeuLimitedErrorCodeConstants.TERMINAL_DG_TEU_START_GT_END);
        }

        // 校验存在
        validateTerminalDgTeuLimitedExists(updateReqVO.getId());

        // 校验有效期是否存在重叠
        if (dateOverlap(updateReqVO, updateReqVO.getId())) {
            throw ServiceExceptionUtil.exception(TerminalDgTeuLimitedErrorCodeConstants.TERMINAL_DG_TEU_DATE_OVERLAP);
        }

        // 更新
        TerminalDgTeuLimitedDO updateObj = TerminalDgTeuLimitedConvert.INSTANCE.convert(updateReqVO);
        terminalDgTeuLimitedMapper.updateById(updateObj);
    }

    @Override
    public void deleteTerminalDgTeuLimited(Long id) {
        // 校验存在
        validateTerminalDgTeuLimitedExists(id);

        // 删除
        terminalDgTeuLimitedMapper.deleteById(id);
    }

    private void validateTerminalDgTeuLimitedExists(Long id) {
        if (terminalDgTeuLimitedMapper.selectById(id) == null) {
            throw ServiceExceptionUtil.exception(TerminalDgTeuLimitedErrorCodeConstants.TERMINAL_DG_TEU_NOT_EXISTED);
        }
    }

    @Override
    public TerminalDgTeuLimitedDO getTerminalDgTeuLimited(Long id) {
        return terminalDgTeuLimitedMapper.selectById(id);
    }

    @Override
    public PageResult<TerminalDgTeuLimitedDO> getTerminalDgTeuLimitedPage(TerminalDgTeuLimitedPageReqVO reqVO) {
        LambdaQueryWrapperX<TerminalDgTeuLimitedDO> queryWrapperX = new LambdaQueryWrapperX<>();
        queryWrapperX.eqIfPresent(TerminalDgTeuLimitedDO::getPolCode, reqVO.getPolCode())
            .eqIfPresent(TerminalDgTeuLimitedDO::getTerminalCode, reqVO.getTerminalCode());
        return terminalDgTeuLimitedMapper.selectPage(reqVO, queryWrapperX);
    }

    @Override
    public Boolean dateOverlap(TerminalDgTeuLimitedBaseVO baseVo) {
        return dateOverlap(baseVo, null);
    }

    private Boolean dateOverlap(TerminalDgTeuLimitedBaseVO baseVo, Long id) {
        LambdaQueryWrapperX<TerminalDgTeuLimitedDO> queryWrapperX = new LambdaQueryWrapperX<>();
        queryWrapperX.eqIfPresent(TerminalDgTeuLimitedDO::getPolCode, baseVo.getPolCode())
            .eqIfPresent(TerminalDgTeuLimitedDO::getTerminalCode, baseVo.getTerminalCode())
            .eqIfPresent(TerminalDgTeuLimitedDO::getImoClass, baseVo.getImoClass());
        if (id != null) {
            queryWrapperX.ne(TerminalDgTeuLimitedDO::getId, id);
        }
        List<TerminalDgTeuLimitedDO> dgTeuLimitedDOList = terminalDgTeuLimitedMapper.selectList(queryWrapperX);
        for (TerminalDgTeuLimitedDO dgTeuDO : dgTeuLimitedDOList) {
            if (CommonUtil.dateOverlap(dgTeuDO.getStartDate(), dgTeuDO.getEndDate(), baseVo.getStartDate(),
                    baseVo.getEndDate())) {
                return true;
            }
        }

        return false;
    }

    @Override
    public void updateEndDates(List<Long> ids, LocalDate endDate) {
        List<TerminalDgTeuLimitedDO> terminalDgTeuLimitedDOList = validAndUpdateEndDate(new HashSet<>(ids), endDate);
        terminalDgTeuLimitedMapper.updateBatch(terminalDgTeuLimitedDOList);
    }

    private List<TerminalDgTeuLimitedDO> validAndUpdateEndDate(Set<Long> ids, LocalDate endDate) {
        // 查询所有item
        List<TerminalDgTeuLimitedDO> terminalDgTeuLimitedDOList = terminalDgTeuLimitedMapper.selectList();

        // 设置id,判断更新后startDate是否小于endDate
        List<TerminalDgTeuLimitedDO> limitedDOList = new ArrayList<>();
        for (TerminalDgTeuLimitedDO teuLimitedDO : terminalDgTeuLimitedDOList) {
            if (ids.contains(teuLimitedDO.getId())) {
                if (teuLimitedDO.getStartDate().isAfter(endDate)) {
                    throw ServiceExceptionUtil
                        .exception(TerminalDgTeuLimitedErrorCodeConstants.TERMINAL_DG_TEU_START_GT_END);
                }
                teuLimitedDO.setEndDate(endDate);
                limitedDOList.add(teuLimitedDO);
            }

            validDateOverlap(limitedDOList, terminalDgTeuLimitedDOList);
        }

        return limitedDOList;
    }

    /**
     * 判断修改后是否出现生效时间重叠
     *
     * @param terminalDgTeuLimitedDOList 修改后的DO列表
     * @param historyDos 数据库原本的DO列表
     */
    private void validDateOverlap(List<TerminalDgTeuLimitedDO> terminalDgTeuLimitedDOList,
                                  List<TerminalDgTeuLimitedDO> historyDos) {
        for (TerminalDgTeuLimitedDO updateDo : terminalDgTeuLimitedDOList) {
            for (TerminalDgTeuLimitedDO historyDo : historyDos) {
                if (updateDo.getId().equals(historyDo.getId())) {
                    continue;
                }

                String updateKey =
                        CommonUtil.buildKey(updateDo.getImoClass(), updateDo.getPolCode(), updateDo.getTerminalCode());
                String historyKey =
                        CommonUtil.buildKey(historyDo.getImoClass(), historyDo.getPolCode(), historyDo.getTerminalCode());
                if (updateKey.equals(historyKey) && CommonUtil.dateOverlap(updateDo.getStartDate(),
                        updateDo.getEndDate(), historyDo.getStartDate(), historyDo.getEndDate())) {
                    throw ServiceExceptionUtil
                            .exception(TerminalDgTeuLimitedErrorCodeConstants.TERMINAL_DG_TEU_DATE_OVERLAP);
                }
            }
        }
    }

}
